package com.ksyun.campus.metaserver.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * 副本放置策略配置
 * 用于配置三副本分配的各种策略参数
 */
@Data
@Component
@ConfigurationProperties(prefix = "minfs.replica-placement")
public class ReplicaPlacementConfig {
    
    /**
     * 副本放置策略类型
     */
    private PlacementStrategy strategy = PlacementStrategy.WEIGHTED;
    
    /**
     * 权重配置
     */
    private WeightConfig weights = new WeightConfig();
    
    /**
     * 负载均衡配置
     */
    private LoadBalanceConfig loadBalance = new LoadBalanceConfig();
    
    /**
     * 机架感知配置
     */
    private RackAwarenessConfig rackAwareness = new RackAwarenessConfig();
    
    /**
     * 故障域配置
     */
    private FaultDomainConfig faultDomain = new FaultDomainConfig();
    
    public enum PlacementStrategy {
        /**
         * 简单轮询策略
         */
        ROUND_ROBIN,
        
        /**
         * 随机选择策略
         */
        RANDOM,
        
        /**
         * 一致性哈希策略（当前默认）
         */
        CONSISTENT_HASH,
        
        /**
         * 加权选择策略（推荐）
         */
        WEIGHTED,
        
        /**
         * 负载感知策略
         */
        LOAD_AWARE
    }
    
    @Data
    public static class WeightConfig {
        /**
         * 容量权重（0.0-1.0）
         */
        private double capacity = 0.4;
        
        /**
         * 负载权重（0.0-1.0）
         */
        private double load = 0.3;
        
        /**
         * 机架分散权重（0.0-1.0）
         */
        private double rack = 0.2;
        
        /**
         * 随机因子权重（0.0-1.0）
         */
        private double random = 0.1;
        
        /**
         * 验证权重总和是否合理
         */
        public boolean isValid() {
            double sum = capacity + load + rack + random;
            return sum > 0.8 && sum <= 1.2; // 允许一定的误差
        }
    }
    
    @Data
    public static class LoadBalanceConfig {
        /**
         * 是否启用负载均衡
         */
        private boolean enabled = true;
        
        /**
         * 负载均衡阈值（使用率超过此值的节点权重降低）
         */
        private double threshold = 0.8;
        
        /**
         * 高负载节点的权重惩罚因子
         */
        private double penaltyFactor = 0.5;
        
        /**
         * 是否考虑网络带宽
         */
        private boolean considerBandwidth = false;
        
        /**
         * 是否考虑磁盘IO
         */
        private boolean considerDiskIo = false;
    }
    
    @Data
    public static class RackAwarenessConfig {
        /**
         * 是否启用机架感知
         */
        private boolean enabled = true;
        
        /**
         * 机架标签键名
         */
        private String labelKey = "rack";
        
        /**
         * 是否强制跨机架分布
         */
        private boolean enforceRackDiversity = false;
        
        /**
         * 最小机架数量要求
         */
        private int minRacks = 2;
        
        /**
         * 同一机架最大副本数
         */
        private int maxReplicasPerRack = 2;
    }
    
    @Data
    public static class FaultDomainConfig {
        /**
         * 是否启用故障域感知
         */
        private boolean enabled = false;
        
        /**
         * 故障域标签键名
         */
        private String labelKey = "fault-domain";
        
        /**
         * 是否考虑网络拓扑
         */
        private boolean considerNetworkTopology = false;
        
        /**
         * 是否避免同一物理服务器
         */
        private boolean avoidSamePhysicalHost = true;
    }
    
    /**
     * 获取有效的权重配置
     * 如果配置无效，返回默认权重
     */
    public WeightConfig getValidatedWeights() {
        if (weights.isValid()) {
            return weights;
        } else {
            WeightConfig defaultWeights = new WeightConfig();
            return defaultWeights;
        }
    }
}
